<!DOCTYPE html>
<html CN>







<head>
	
	
	<link rel="stylesheet" href="/css/allinone.min.css"> 

	
	<!-- Global Site Tag (gtag.js) - Google Analytics -->
	<script async src="https://www.googletagmanager.com/gtag/js?id=UA-42863699-1"></script>
	<script>
		window.dataLayer = window.dataLayer || [];
		function gtag(){dataLayer.push(arguments);}
		gtag('js', new Date());
		gtag('config', 'UA-42863699-1');
	</script>
	

	<meta charset="utf-8" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge" />

	<title>kubelet 源码分析：statusManager 和 probeManager | Cizixs Write Here</title>

	<meta name="HandheldFriendly" content="True" />
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
	<meta name="generator" content="hexo">
	<meta name="author" content="Cizixs Wu">
	<meta name="description" content="">

	
	<meta name="keywords" content="">
	

	
	<link rel="shortcut icon" href="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxfovpzyj30740743yg.jpg">
	

	
	<meta name="theme-color" content="#3c484e">
	<meta name="msapplication-TileColor" content="#3c484e">
	

	

	

	<meta property="og:site_name" content="Cizixs Write Here">
	<meta property="og:type" content="article">
	<meta property="og:title" content="kubelet 源码分析：statusManager 和 probeManager | Cizixs Write Here">
	<meta property="og:description" content="">
	<meta property="og:url" content="http://cizixs.com/2017/06/12/kubelet-source-code-analysis-part4-status-manager/">

	
	<meta property="article:published_time" content="2017-06-12T00:06:00+08:00"/> 
	<meta property="article:author" content="Cizixs Wu">
	<meta property="article:published_first" content="Cizixs Write Here, /2017/06/12/kubelet-source-code-analysis-part4-status-manager/" />
	

	
	
	<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
	

	
	<script src="https://cdn.staticfile.org/highlight.js/9.10.0/highlight.min.js"></script>
	

	
	
<link rel="stylesheet" href="/css/prism-base16-ateliersulphurpool.light.css" type="text/css"></head>
<body class="post-template">
    <div class="site-wrapper">
        




<header class="site-header outer" style="z-index: 999">
    <div class="inner">
        
<nav class="site-nav"> 
    <div class="site-nav-left">
        <ul class="nav">
            <li>
                
                <a href="/" title="Home">Home</a>
                
            </li>
            
            
            <li>
                <a href="/about" title="About">About</a>
            </li>
            
            <li>
                <a href="/archives" title="Archives">Archives</a>
            </li>
            
            
        </ul> 
    </div>
    <div class="site-nav-right">
        
<div class="social-links" >
    
    <a class="social-link" title="weibo" href="https://weibo.com/1921727853" target="_blank" rel="noopener">
        <svg viewBox="0 0 1141 1024" xmlns="http://www.w3.org/2000/svg"><path d="M916.48 518.144q27.648 21.504 38.912 51.712t9.216 62.976-14.336 65.536-31.744 59.392q-34.816 48.128-78.848 81.92t-91.136 56.32-94.72 35.328-89.6 18.944-75.264 7.68-51.712 1.536-49.152-2.56-68.096-10.24-78.336-21.504-79.872-36.352-74.24-55.296-59.904-78.848q-16.384-29.696-22.016-63.488t-5.632-86.016q0-22.528 7.68-51.2t27.136-63.488 53.248-75.776 86.016-90.112q51.2-48.128 105.984-85.504t117.248-57.856q28.672-10.24 63.488-11.264t57.344 11.264q10.24 11.264 19.456 23.04t12.288 29.184q3.072 14.336 0.512 27.648t-5.632 26.624-5.12 25.6 2.048 22.528q17.408 2.048 33.792-1.536t31.744-9.216 31.232-11.776 33.28-9.216q27.648-5.12 54.784-4.608t49.152 7.68 36.352 22.016 17.408 38.4q2.048 14.336-2.048 26.624t-8.704 23.04-7.168 22.016 1.536 23.552q3.072 7.168 14.848 13.312t27.136 12.288 32.256 13.312 29.184 16.384zM658.432 836.608q26.624-16.384 53.76-45.056t44.032-64 18.944-75.776-20.48-81.408q-19.456-33.792-47.616-57.344t-62.976-37.376-74.24-19.968-80.384-6.144q-78.848 0-139.776 16.384t-105.472 43.008-72.192 60.416-38.912 68.608q-11.264 33.792-6.656 67.072t20.992 62.976 42.496 53.248 57.856 37.888q58.368 25.6 119.296 32.256t116.224 0.512 100.864-21.504 74.24-33.792zM524.288 513.024q20.48 8.192 38.912 18.432t32.768 27.648q10.24 12.288 17.92 30.72t10.752 39.424 1.536 42.496-9.728 38.912q-8.192 18.432-19.968 37.376t-28.672 35.328-40.448 29.184-57.344 18.944q-61.44 11.264-117.76-11.264t-88.064-74.752q-12.288-39.936-13.312-70.656t16.384-66.56q13.312-27.648 40.448-51.712t62.464-38.912 75.264-17.408 78.848 12.8zM361.472 764.928q37.888 3.072 57.856-18.432t21.504-48.128-15.36-47.616-52.736-16.896q-27.648 3.072-43.008 23.552t-17.408 43.52 9.728 42.496 39.424 21.504zM780.288 6.144q74.752 0 139.776 19.968t113.664 57.856 76.288 92.16 27.648 122.88q0 33.792-16.384 50.688t-35.328 17.408-35.328-14.336-16.384-45.568q0-40.96-22.528-77.824t-59.392-64.512-84.48-43.52-96.768-15.872q-31.744 0-47.104-15.36t-14.336-34.304 18.944-34.304 51.712-15.36zM780.288 169.984q95.232 0 144.384 48.64t49.152 146.944q0 30.72-10.24 43.52t-22.528 11.264-22.528-14.848-10.24-35.84q0-60.416-34.816-96.256t-93.184-35.84q-19.456 0-28.672-10.752t-9.216-23.04 9.728-23.04 28.16-10.752z" /></svg>
    </a>
    

    
    <a class="social-link" title="github" href="https://github.com/cizixs" target="_blank" rel="noopener">
        <svg viewBox="0 0 1049 1024" xmlns="http://www.w3.org/2000/svg"><path d="M524.979332 0C234.676191 0 0 234.676191 0 524.979332c0 232.068678 150.366597 428.501342 358.967656 498.035028 26.075132 5.215026 35.636014-11.299224 35.636014-25.205961 0-12.168395-0.869171-53.888607-0.869171-97.347161-146.020741 31.290159-176.441729-62.580318-176.441729-62.580318-23.467619-60.841976-58.234462-76.487055-58.234463-76.487055-47.804409-32.15933 3.476684-32.15933 3.476685-32.15933 53.019436 3.476684 80.83291 53.888607 80.83291 53.888607 46.935238 79.963739 122.553122 57.365291 152.97411 43.458554 4.345855-33.897672 18.252593-57.365291 33.028501-70.402857-116.468925-12.168395-239.022047-57.365291-239.022047-259.012982 0-57.365291 20.860106-104.300529 53.888607-140.805715-5.215026-13.037566-23.467619-66.926173 5.215027-139.067372 0 0 44.327725-13.906737 144.282399 53.888607 41.720212-11.299224 86.917108-17.383422 131.244833-17.383422s89.524621 6.084198 131.244833 17.383422C756.178839 203.386032 800.506564 217.29277 800.506564 217.29277c28.682646 72.1412 10.430053 126.029806 5.215026 139.067372 33.897672 36.505185 53.888607 83.440424 53.888607 140.805715 0 201.64769-122.553122 245.975415-239.891218 259.012982 19.121764 16.514251 35.636014 47.804409 35.636015 97.347161 0 70.402857-0.869171 126.898978-0.869172 144.282399 0 13.906737 9.560882 30.420988 35.636015 25.205961 208.601059-69.533686 358.967656-265.96635 358.967655-498.035028C1049.958663 234.676191 814.413301 0 524.979332 0z" /></svg>
    </a>
    

    
    <a class="social-link" title="stackoverflow" href="https://stackoverflow.com/users/1925083/cizixs" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M15 21h-10v-2h10v2zm6-11.665l-1.621-9.335-1.993.346 1.62 9.335 1.994-.346zm-5.964 6.937l-9.746-.975-.186 2.016 9.755.879.177-1.92zm.538-2.587l-9.276-2.608-.526 1.954 9.306 2.5.496-1.846zm1.204-2.413l-8.297-4.864-1.029 1.743 8.298 4.865 1.028-1.744zm1.866-1.467l-5.339-7.829-1.672 1.14 5.339 7.829 1.672-1.14zm-2.644 4.195v8h-12v-8h-2v10h16v-10h-2z"/></svg>
    </a>
    

    

    
    <a class="social-link" title="twitter" href="https://twitter.com/cizixs" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z"/></svg>

    </a>
    

    
    <a class="social-link" title="instagram" href="https://www.instagram.com/cizixs/" target="_blank" rel="noopener">
        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/></svg>
    </a>
    
    
    
</div>
    </div>
</nav>
    </div>
</header>


<main id="site-main" class="site-main outer" role="main">
    <div class="inner">
        <header class="post-full-header">
            <section class="post-full-meta">
                <time  class="post-full-meta-date" datetime="2017-06-11T16:00:00.000Z" itemprop="datePublished">
                    2017-06-12
                </time>
                
                <span class="date-divider">/</span>
                
                <a href="/categories/blog/">blog</a>&nbsp;&nbsp;
                
                
            </section>
            <h1 class="post-full-title">kubelet 源码分析：statusManager 和 probeManager</h1>
        </header>
        <article class="post-full no-image">
            
            <section class="post-full-content">
                <div id="lightgallery" class="markdown-body">
                    <h2 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h2><p>在 kubelet 初始化的时候，会创建 statusManager 和 probeManager，两者都和 pod 的状态有关系，因此我们放到一起来讲解。</p>
<p>statusManager 负责维护状态信息，并把 pod 状态更新到 apiserver，但是它并不负责监控 pod 状态的变化，而是提供对应的接口供其他组件调用，比如 probeManager。probeManager 会定时去监控 pod 中容器的健康状况，一旦发现状态发生变化，就调用 statusManager 提供的方法更新 pod 的状态。</p>
<pre class=" language-go"><code class="language-go">klet<span class="token punctuation">.</span>statusManager <span class="token operator">=</span> status<span class="token punctuation">.</span><span class="token function">NewManager</span><span class="token punctuation">(</span>kubeClient<span class="token punctuation">,</span> klet<span class="token punctuation">.</span>podManager<span class="token punctuation">)</span>
klet<span class="token punctuation">.</span>probeManager <span class="token operator">=</span> prober<span class="token punctuation">.</span><span class="token function">NewManager</span><span class="token punctuation">(</span>
        klet<span class="token punctuation">.</span>statusManager<span class="token punctuation">,</span>
        klet<span class="token punctuation">.</span>livenessManager<span class="token punctuation">,</span>
        klet<span class="token punctuation">.</span>runner<span class="token punctuation">,</span>
        containerRefManager<span class="token punctuation">,</span>
        kubeDeps<span class="token punctuation">.</span>Recorder<span class="token punctuation">)</span>
</code></pre>
<h2 id="StatusManager"><a href="#StatusManager" class="headerlink" title="StatusManager"></a>StatusManager</h2><p>statusManager 对应的代码在 <code>pkg/kubelet/status/status_manager.go</code> 文件中，</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">type</span> PodStatusProvider <span class="token keyword">interface</span> <span class="token punctuation">{</span>
    <span class="token function">GetPodStatus</span><span class="token punctuation">(</span>uid types<span class="token punctuation">.</span>UID<span class="token punctuation">)</span> <span class="token punctuation">(</span>api<span class="token punctuation">.</span>PodStatus<span class="token punctuation">,</span> <span class="token builtin">bool</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> Manager <span class="token keyword">interface</span> <span class="token punctuation">{</span>
    PodStatusProvider

    <span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token function">SetPodStatus</span><span class="token punctuation">(</span>pod <span class="token operator">*</span>api<span class="token punctuation">.</span>Pod<span class="token punctuation">,</span> status api<span class="token punctuation">.</span>PodStatus<span class="token punctuation">)</span>
    <span class="token function">SetContainerReadiness</span><span class="token punctuation">(</span>podUID types<span class="token punctuation">.</span>UID<span class="token punctuation">,</span> containerID kubecontainer<span class="token punctuation">.</span>ContainerID<span class="token punctuation">,</span> ready <span class="token builtin">bool</span><span class="token punctuation">)</span>
    <span class="token function">TerminatePod</span><span class="token punctuation">(</span>pod <span class="token operator">*</span>api<span class="token punctuation">.</span>Pod<span class="token punctuation">)</span>
    <span class="token function">RemoveOrphanedStatuses</span><span class="token punctuation">(</span>podUIDs <span class="token keyword">map</span><span class="token punctuation">[</span>types<span class="token punctuation">.</span>UID<span class="token punctuation">]</span><span class="token builtin">bool</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
<p>这个接口的方法可以分成三组：获取某个 pod 的状态、后台运行 goroutine 执行同步工作、修改 pod 的状态。修改状态的方法有多个，每个都有不同的用途：</p>
<ul>
<li>SetPodStatus：如果 pod 的状态发生了变化，会调用这个方法，把新状态更新到 apiserver，一般在 kubelet 维护 pod 生命周期的时候会调用</li>
<li>SetContainerReadiness：如果健康检查发现 pod 中容器的健康状态发生变化，会调用这个方法，修改 pod 的健康状态</li>
<li>TerminatePod：kubelet 在删除 pod 的时候，会调用这个方法，把 pod 中所有的容器设置为 terminated 状态</li>
<li>RemoveOrphanedStatuses：删除孤儿 pod，直接把对应的状态数据从缓存中删除即可</li>
</ul>
<p><code>Start()</code> 方法是在 kubelet 运行的时候调用的，它会启动一个 goroutine 执行更新操作：</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">const</span> syncPeriod <span class="token operator">=</span> <span class="token number">10</span> <span class="token operator">*</span> time<span class="token punctuation">.</span>Second

<span class="token keyword">func</span> <span class="token punctuation">(</span>m <span class="token operator">*</span>manager<span class="token punctuation">)</span> <span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token operator">...</span><span class="token operator">...</span>
    glog<span class="token punctuation">.</span><span class="token function">Info</span><span class="token punctuation">(</span><span class="token string">"Starting to sync pod status with apiserver"</span><span class="token punctuation">)</span>
    syncTicker <span class="token operator">:=</span> time<span class="token punctuation">.</span><span class="token function">Tick</span><span class="token punctuation">(</span>syncPeriod<span class="token punctuation">)</span>
    <span class="token comment" spellcheck="true">// syncPod and syncBatch share the same go routine to avoid sync races.</span>
    <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Forever</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">select</span> <span class="token punctuation">{</span>
        <span class="token keyword">case</span> syncRequest <span class="token operator">:=</span> <span class="token operator">&lt;-</span>m<span class="token punctuation">.</span>podStatusChannel<span class="token punctuation">:</span>
            m<span class="token punctuation">.</span><span class="token function">syncPod</span><span class="token punctuation">(</span>syncRequest<span class="token punctuation">.</span>podUID<span class="token punctuation">,</span> syncRequest<span class="token punctuation">.</span>status<span class="token punctuation">)</span>
        <span class="token keyword">case</span> <span class="token operator">&lt;-</span>syncTicker<span class="token punctuation">:</span>
            m<span class="token punctuation">.</span><span class="token function">syncBatch</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
<p>这个 goroutine 就能不断地从两个 channel 监听数据进行处理：<code>syncTicker</code> 是个定时器，也就是说它会定时保证 apiserver 和自己缓存的最新 pod 状态保持一致；<code>podStatusChannel</code> 是所有 pod 状态更新发送到的地方，调用方不会直接操作这个 channel，而是通过调用上面提到的修改状态的各种方法，这些方法内部会往这个 channel 写数据。</p>
<p><code>m.syncPod</code> 根据参数中的 pod 和它的状态信息对 apiserver 中的数据进行更新，如果发现 pod 已经被删除也会把它从内部数据结构中删除。</p>
<h2 id="ProbeManager"><a href="#ProbeManager" class="headerlink" title="ProbeManager"></a>ProbeManager</h2><p>probeManager 检测 <a href="https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/" target="_blank" rel="noopener">pod 中容器的健康状态</a>，目前有两种 probe：readiness 和 liveness。<strong>readinessProbe</strong> 检测容器是否可以接受请求，如果检测结果失败，则将其从 service 的 endpoints 中移除，后续的请求也就不会发送给这个容器；livenessProbe 检测容器是否存活，如果检测结果失败，kubelet 会杀死这个容器，并重启一个新的（除非 RestartPolicy 设置成了 Never）。</p>
<p>并不是所有的 pod 中的容器都有健康检查的探针，如果没有，则不对容器进行检测，默认认为容器是正常的。在每次创建新 pod 的时候，kubelet 都会调用 <code>probeManager.AddPod(pod)</code> 方法，它对应的实现在 <code>pkg/kubelet/prober/prober_manager.go</code> 文件中：</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token punctuation">(</span>m <span class="token operator">*</span>manager<span class="token punctuation">)</span> <span class="token function">AddPod</span><span class="token punctuation">(</span>pod <span class="token operator">*</span>api<span class="token punctuation">.</span>Pod<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    m<span class="token punctuation">.</span>workerLock<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">defer</span> m<span class="token punctuation">.</span>workerLock<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    key <span class="token operator">:=</span> probeKey<span class="token punctuation">{</span>podUID<span class="token punctuation">:</span> pod<span class="token punctuation">.</span>UID<span class="token punctuation">}</span>
    <span class="token keyword">for</span> <span class="token boolean">_</span><span class="token punctuation">,</span> c <span class="token operator">:=</span> <span class="token keyword">range</span> pod<span class="token punctuation">.</span>Spec<span class="token punctuation">.</span>Containers <span class="token punctuation">{</span>
        key<span class="token punctuation">.</span>containerName <span class="token operator">=</span> c<span class="token punctuation">.</span>Name

        <span class="token keyword">if</span> c<span class="token punctuation">.</span>ReadinessProbe <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            key<span class="token punctuation">.</span>probeType <span class="token operator">=</span> readiness
            <span class="token keyword">if</span> <span class="token boolean">_</span><span class="token punctuation">,</span> ok <span class="token operator">:=</span> m<span class="token punctuation">.</span>workers<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">;</span> ok <span class="token punctuation">{</span>
                glog<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"Readiness probe already exists! %v - %v"</span><span class="token punctuation">,</span>
                    format<span class="token punctuation">.</span><span class="token function">Pod</span><span class="token punctuation">(</span>pod<span class="token punctuation">)</span><span class="token punctuation">,</span> c<span class="token punctuation">.</span>Name<span class="token punctuation">)</span>
                <span class="token keyword">return</span>
            <span class="token punctuation">}</span>
            w <span class="token operator">:=</span> <span class="token function">newWorker</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span> readiness<span class="token punctuation">,</span> pod<span class="token punctuation">,</span> c<span class="token punctuation">)</span>
            m<span class="token punctuation">.</span>workers<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> w
            <span class="token keyword">go</span> w<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">if</span> c<span class="token punctuation">.</span>LivenessProbe <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
            key<span class="token punctuation">.</span>probeType <span class="token operator">=</span> liveness
            <span class="token keyword">if</span> <span class="token boolean">_</span><span class="token punctuation">,</span> ok <span class="token operator">:=</span> m<span class="token punctuation">.</span>workers<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">;</span> ok <span class="token punctuation">{</span>
                glog<span class="token punctuation">.</span><span class="token function">Errorf</span><span class="token punctuation">(</span><span class="token string">"Liveness probe already exists! %v - %v"</span><span class="token punctuation">,</span>
                    format<span class="token punctuation">.</span><span class="token function">Pod</span><span class="token punctuation">(</span>pod<span class="token punctuation">)</span><span class="token punctuation">,</span> c<span class="token punctuation">.</span>Name<span class="token punctuation">)</span>
                <span class="token keyword">return</span>
            <span class="token punctuation">}</span>
            w <span class="token operator">:=</span> <span class="token function">newWorker</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span> liveness<span class="token punctuation">,</span> pod<span class="token punctuation">,</span> c<span class="token punctuation">)</span>
            m<span class="token punctuation">.</span>workers<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> w
            <span class="token keyword">go</span> w<span class="token punctuation">.</span><span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre>
<p>遍历 pod 中的容器，如果其定义了 readiness 或者 liveness，就创建一个 worker，并启动一个 goroutine 在后台运行这个 worker。</p>
<p><code>pkg/kubelet/prober/worker.go</code>：</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token punctuation">(</span>w <span class="token operator">*</span>worker<span class="token punctuation">)</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    probeTickerPeriod <span class="token operator">:=</span> time<span class="token punctuation">.</span><span class="token function">Duration</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>spec<span class="token punctuation">.</span>PeriodSeconds<span class="token punctuation">)</span> <span class="token operator">*</span> time<span class="token punctuation">.</span>Second
    probeTicker <span class="token operator">:=</span> time<span class="token punctuation">.</span><span class="token function">NewTicker</span><span class="token punctuation">(</span>probeTickerPeriod<span class="token punctuation">)</span>

    <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        probeTicker<span class="token punctuation">.</span><span class="token function">Stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
        <span class="token keyword">if</span> <span class="token operator">!</span>w<span class="token punctuation">.</span>containerID<span class="token punctuation">.</span><span class="token function">IsEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            w<span class="token punctuation">.</span>resultsManager<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>containerID<span class="token punctuation">)</span>
        <span class="token punctuation">}</span>

        w<span class="token punctuation">.</span>probeManager<span class="token punctuation">.</span><span class="token function">removeWorker</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>pod<span class="token punctuation">.</span>UID<span class="token punctuation">,</span> w<span class="token punctuation">.</span>container<span class="token punctuation">.</span>Name<span class="token punctuation">,</span> w<span class="token punctuation">.</span>probeType<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    time<span class="token punctuation">.</span><span class="token function">Sleep</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span><span class="token function">Duration</span><span class="token punctuation">(</span>rand<span class="token punctuation">.</span><span class="token function">Float64</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> <span class="token function">float64</span><span class="token punctuation">(</span>probeTickerPeriod<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

probeLoop<span class="token punctuation">:</span>
    <span class="token keyword">for</span> w<span class="token punctuation">.</span><span class="token function">doProbe</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment" spellcheck="true">// Wait for next probe tick.</span>
        <span class="token keyword">select</span> <span class="token punctuation">{</span>
        <span class="token keyword">case</span> <span class="token operator">&lt;-</span>w<span class="token punctuation">.</span>stopCh<span class="token punctuation">:</span>
            <span class="token keyword">break</span> probeLoop
        <span class="token keyword">case</span> <span class="token operator">&lt;-</span>probeTicker<span class="token punctuation">.</span>C<span class="token punctuation">:</span>
            <span class="token comment" spellcheck="true">// continue</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>w <span class="token operator">*</span>worker<span class="token punctuation">)</span> <span class="token function">doProbe</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">(</span>keepGoing <span class="token builtin">bool</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">defer</span> <span class="token keyword">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">recover</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span> 
    <span class="token keyword">defer</span> runtime<span class="token punctuation">.</span><span class="token function">HandleCrash</span><span class="token punctuation">(</span><span class="token keyword">func</span><span class="token punctuation">(</span><span class="token boolean">_</span> <span class="token keyword">interface</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> keepGoing <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>

    <span class="token comment" spellcheck="true">// pod 没有被创建，或者已经被删除了，直接跳过检测，但是会继续检测</span>
    status<span class="token punctuation">,</span> ok <span class="token operator">:=</span> w<span class="token punctuation">.</span>probeManager<span class="token punctuation">.</span>statusManager<span class="token punctuation">.</span><span class="token function">GetPodStatus</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>pod<span class="token punctuation">.</span>UID<span class="token punctuation">)</span>
    <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span>
        glog<span class="token punctuation">.</span><span class="token function">V</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Infof</span><span class="token punctuation">(</span><span class="token string">"No status for pod: %v"</span><span class="token punctuation">,</span> format<span class="token punctuation">.</span><span class="token function">Pod</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>pod<span class="token punctuation">)</span><span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// pod 已经退出（不管是成功还是失败），直接返回，并终止 worker</span>
    <span class="token keyword">if</span> status<span class="token punctuation">.</span>Phase <span class="token operator">==</span> api<span class="token punctuation">.</span>PodFailed <span class="token operator">||</span> status<span class="token punctuation">.</span>Phase <span class="token operator">==</span> api<span class="token punctuation">.</span>PodSucceeded <span class="token punctuation">{</span>
        glog<span class="token punctuation">.</span><span class="token function">V</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Infof</span><span class="token punctuation">(</span><span class="token string">"Pod %v %v, exiting probe worker"</span><span class="token punctuation">,</span>
            format<span class="token punctuation">.</span><span class="token function">Pod</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>pod<span class="token punctuation">)</span><span class="token punctuation">,</span> status<span class="token punctuation">.</span>Phase<span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token boolean">false</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 容器没有创建，或者已经删除了，直接返回，并继续检测，等待更多的信息</span>
    c<span class="token punctuation">,</span> ok <span class="token operator">:=</span> api<span class="token punctuation">.</span><span class="token function">GetContainerStatus</span><span class="token punctuation">(</span>status<span class="token punctuation">.</span>ContainerStatuses<span class="token punctuation">,</span> w<span class="token punctuation">.</span>container<span class="token punctuation">.</span>Name<span class="token punctuation">)</span>
    <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token operator">||</span> <span class="token function">len</span><span class="token punctuation">(</span>c<span class="token punctuation">.</span>ContainerID<span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span> <span class="token punctuation">{</span>
        glog<span class="token punctuation">.</span><span class="token function">V</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Infof</span><span class="token punctuation">(</span><span class="token string">"Probe target container not found: %v - %v"</span><span class="token punctuation">,</span>
            format<span class="token punctuation">.</span><span class="token function">Pod</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>pod<span class="token punctuation">)</span><span class="token punctuation">,</span> w<span class="token punctuation">.</span>container<span class="token punctuation">.</span>Name<span class="token punctuation">)</span>
        <span class="token keyword">return</span> <span class="token boolean">true</span> 
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// pod 更新了容器，使用最新的容器信息</span>
    <span class="token keyword">if</span> w<span class="token punctuation">.</span>containerID<span class="token punctuation">.</span><span class="token function">String</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">!=</span> c<span class="token punctuation">.</span>ContainerID <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token operator">!</span>w<span class="token punctuation">.</span>containerID<span class="token punctuation">.</span><span class="token function">IsEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            w<span class="token punctuation">.</span>resultsManager<span class="token punctuation">.</span><span class="token function">Remove</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>containerID<span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
        w<span class="token punctuation">.</span>containerID <span class="token operator">=</span> kubecontainer<span class="token punctuation">.</span><span class="token function">ParseContainerID</span><span class="token punctuation">(</span>c<span class="token punctuation">.</span>ContainerID<span class="token punctuation">)</span>
        w<span class="token punctuation">.</span>resultsManager<span class="token punctuation">.</span><span class="token function">Set</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>containerID<span class="token punctuation">,</span> w<span class="token punctuation">.</span>initialValue<span class="token punctuation">,</span> w<span class="token punctuation">.</span>pod<span class="token punctuation">)</span>
        w<span class="token punctuation">.</span>onHold <span class="token operator">=</span> <span class="token boolean">false</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">if</span> w<span class="token punctuation">.</span>onHold <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">if</span> c<span class="token punctuation">.</span>State<span class="token punctuation">.</span>Running <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        glog<span class="token punctuation">.</span><span class="token function">V</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Infof</span><span class="token punctuation">(</span><span class="token string">"Non-running container probed: %v - %v"</span><span class="token punctuation">,</span>
            format<span class="token punctuation">.</span><span class="token function">Pod</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>pod<span class="token punctuation">)</span><span class="token punctuation">,</span> w<span class="token punctuation">.</span>container<span class="token punctuation">.</span>Name<span class="token punctuation">)</span>
        <span class="token keyword">if</span> <span class="token operator">!</span>w<span class="token punctuation">.</span>containerID<span class="token punctuation">.</span><span class="token function">IsEmpty</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            w<span class="token punctuation">.</span>resultsManager<span class="token punctuation">.</span><span class="token function">Set</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>containerID<span class="token punctuation">,</span> results<span class="token punctuation">.</span>Failure<span class="token punctuation">,</span> w<span class="token punctuation">.</span>pod<span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
        <span class="token comment" spellcheck="true">// 容器失败退出，并且不会再重启，终止 worker</span>
        <span class="token keyword">return</span> c<span class="token punctuation">.</span>State<span class="token punctuation">.</span>Terminated <span class="token operator">==</span> <span class="token boolean">nil</span> <span class="token operator">||</span>
            w<span class="token punctuation">.</span>pod<span class="token punctuation">.</span>Spec<span class="token punctuation">.</span>RestartPolicy <span class="token operator">!=</span> api<span class="token punctuation">.</span>RestartPolicyNever
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 容器启动时间太短，没有超过配置的初始化等待时间 InitialDelaySeconds</span>
    <span class="token keyword">if</span> <span class="token function">int32</span><span class="token punctuation">(</span>time<span class="token punctuation">.</span><span class="token function">Since</span><span class="token punctuation">(</span>c<span class="token punctuation">.</span>State<span class="token punctuation">.</span>Running<span class="token punctuation">.</span>StartedAt<span class="token punctuation">.</span>Time<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Seconds</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">&lt;</span> w<span class="token punctuation">.</span>spec<span class="token punctuation">.</span>InitialDelaySeconds <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 调用 prober 进行检测容器的状态</span>
    result<span class="token punctuation">,</span> err <span class="token operator">:=</span> w<span class="token punctuation">.</span>probeManager<span class="token punctuation">.</span>prober<span class="token punctuation">.</span><span class="token function">probe</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>probeType<span class="token punctuation">,</span> w<span class="token punctuation">.</span>pod<span class="token punctuation">,</span> status<span class="token punctuation">,</span> w<span class="token punctuation">.</span>container<span class="token punctuation">,</span> w<span class="token punctuation">.</span>containerID<span class="token punctuation">)</span>
    <span class="token keyword">if</span> err <span class="token operator">!=</span> <span class="token boolean">nil</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">if</span> w<span class="token punctuation">.</span>lastResult <span class="token operator">==</span> result <span class="token punctuation">{</span>
        w<span class="token punctuation">.</span>resultRun<span class="token operator">++</span>
    <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
        w<span class="token punctuation">.</span>lastResult <span class="token operator">=</span> result
        w<span class="token punctuation">.</span>resultRun <span class="token operator">=</span> <span class="token number">1</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 如果容器退出，并且没有超过最大的失败次数，则继续检测</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>result <span class="token operator">==</span> results<span class="token punctuation">.</span>Failure <span class="token operator">&amp;&amp;</span> w<span class="token punctuation">.</span>resultRun <span class="token operator">&lt;</span> <span class="token function">int</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>spec<span class="token punctuation">.</span>FailureThreshold<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">||</span>
        <span class="token punctuation">(</span>result <span class="token operator">==</span> results<span class="token punctuation">.</span>Success <span class="token operator">&amp;&amp;</span> w<span class="token punctuation">.</span>resultRun <span class="token operator">&lt;</span> <span class="token function">int</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>spec<span class="token punctuation">.</span>SuccessThreshold<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span>

    <span class="token comment" spellcheck="true">// 保存最新的检测结果</span>
    w<span class="token punctuation">.</span>resultsManager<span class="token punctuation">.</span><span class="token function">Set</span><span class="token punctuation">(</span>w<span class="token punctuation">.</span>containerID<span class="token punctuation">,</span> result<span class="token punctuation">,</span> w<span class="token punctuation">.</span>pod<span class="token punctuation">)</span>

    <span class="token keyword">if</span> w<span class="token punctuation">.</span>probeType <span class="token operator">==</span> liveness <span class="token operator">&amp;&amp;</span> result <span class="token operator">==</span> results<span class="token punctuation">.</span>Failure <span class="token punctuation">{</span>
        <span class="token comment" spellcheck="true">// 容器 liveness 检测失败，需要删除容器并重新创建，在新容器成功创建出来之前，暂停检测</span>
        w<span class="token punctuation">.</span>onHold <span class="token operator">=</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">return</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span>
</code></pre>
<p>每次检测的时候都会用 <code>w.resultsManager.Set(w.containerID, result, w.pod)</code> 来保存检测结果，<code>resultsManager</code> 的代码在 <code>pkg/kubelet/prober/results/results_manager.go</code>：</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token punctuation">(</span>m <span class="token operator">*</span>manager<span class="token punctuation">)</span> <span class="token function">Set</span><span class="token punctuation">(</span>id kubecontainer<span class="token punctuation">.</span>ContainerID<span class="token punctuation">,</span> result Result<span class="token punctuation">,</span> pod <span class="token operator">*</span>api<span class="token punctuation">.</span>Pod<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">if</span> m<span class="token punctuation">.</span><span class="token function">setInternal</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span> result<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        m<span class="token punctuation">.</span>updates <span class="token operator">&lt;-</span> Update<span class="token punctuation">{</span>id<span class="token punctuation">,</span> result<span class="token punctuation">,</span> pod<span class="token punctuation">.</span>UID<span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>m <span class="token operator">*</span>manager<span class="token punctuation">)</span> <span class="token function">setInternal</span><span class="token punctuation">(</span>id kubecontainer<span class="token punctuation">.</span>ContainerID<span class="token punctuation">,</span> result Result<span class="token punctuation">)</span> <span class="token builtin">bool</span> <span class="token punctuation">{</span>
    m<span class="token punctuation">.</span><span class="token function">Lock</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">defer</span> m<span class="token punctuation">.</span><span class="token function">Unlock</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    prev<span class="token punctuation">,</span> exists <span class="token operator">:=</span> m<span class="token punctuation">.</span>cache<span class="token punctuation">[</span>id<span class="token punctuation">]</span>
    <span class="token keyword">if</span> <span class="token operator">!</span>exists <span class="token operator">||</span> prev <span class="token operator">!=</span> result <span class="token punctuation">{</span>
        m<span class="token punctuation">.</span>cache<span class="token punctuation">[</span>id<span class="token punctuation">]</span> <span class="token operator">=</span> result
        <span class="token keyword">return</span> <span class="token boolean">true</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">return</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>m <span class="token operator">*</span>manager<span class="token punctuation">)</span> <span class="token function">Updates</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">&lt;-</span><span class="token keyword">chan</span> Update <span class="token punctuation">{</span>
    <span class="token keyword">return</span> m<span class="token punctuation">.</span>updates
<span class="token punctuation">}</span>
</code></pre>
<p>它把结果保存在缓存中，并发送到 <code>m.updates</code> 管道。对于 liveness 来说，它的管道消费者是 kubelet，还记得 <code>syncLoopIteration</code> 中的这段代码逻辑吗？</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">case</span> update <span class="token operator">:=</span> <span class="token operator">&lt;-</span>kl<span class="token punctuation">.</span>livenessManager<span class="token punctuation">.</span><span class="token function">Updates</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">:</span>
        <span class="token keyword">if</span> update<span class="token punctuation">.</span>Result <span class="token operator">==</span> proberesults<span class="token punctuation">.</span>Failure <span class="token punctuation">{</span>
            <span class="token comment" spellcheck="true">// The liveness manager detected a failure; sync the pod.</span>
            pod<span class="token punctuation">,</span> ok <span class="token operator">:=</span> kl<span class="token punctuation">.</span>podManager<span class="token punctuation">.</span><span class="token function">GetPodByUID</span><span class="token punctuation">(</span>update<span class="token punctuation">.</span>PodUID<span class="token punctuation">)</span>
            <span class="token keyword">if</span> <span class="token operator">!</span>ok <span class="token punctuation">{</span>
                <span class="token comment" spellcheck="true">// If the pod no longer exists, ignore the update.</span>
                glog<span class="token punctuation">.</span><span class="token function">V</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Infof</span><span class="token punctuation">(</span><span class="token string">"SyncLoop (container unhealthy): ignore irrelevant update: %#v"</span><span class="token punctuation">,</span> update<span class="token punctuation">)</span>
                <span class="token keyword">break</span>
            <span class="token punctuation">}</span>
            glog<span class="token punctuation">.</span><span class="token function">V</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">Infof</span><span class="token punctuation">(</span><span class="token string">"SyncLoop (container unhealthy): %q"</span><span class="token punctuation">,</span> format<span class="token punctuation">.</span><span class="token function">Pod</span><span class="token punctuation">(</span>pod<span class="token punctuation">)</span><span class="token punctuation">)</span>
            handler<span class="token punctuation">.</span><span class="token function">HandlePodSyncs</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">*</span>api<span class="token punctuation">.</span>Pod<span class="token punctuation">{</span>pod<span class="token punctuation">}</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
</code></pre>
<p>因为 liveness 关系者 pod 的生死，因此需要 kubelet 的处理逻辑。而 readiness 即使失败也不会重新创建 pod，它的处理逻辑是不同的，它的处理代码同样在 <code>pkg/kubelet/prober/prober_manager.go</code>：</p>
<pre class=" language-go"><code class="language-go"><span class="token keyword">func</span> <span class="token punctuation">(</span>m <span class="token operator">*</span>manager<span class="token punctuation">)</span> <span class="token function">Start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">go</span> wait<span class="token punctuation">.</span><span class="token function">Forever</span><span class="token punctuation">(</span>m<span class="token punctuation">.</span>updateReadiness<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">func</span> <span class="token punctuation">(</span>m <span class="token operator">*</span>manager<span class="token punctuation">)</span> <span class="token function">updateReadiness</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    update <span class="token operator">:=</span> <span class="token operator">&lt;-</span>m<span class="token punctuation">.</span>readinessManager<span class="token punctuation">.</span><span class="token function">Updates</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    ready <span class="token operator">:=</span> update<span class="token punctuation">.</span>Result <span class="token operator">==</span> results<span class="token punctuation">.</span>Success
    m<span class="token punctuation">.</span>statusManager<span class="token punctuation">.</span><span class="token function">SetContainerReadiness</span><span class="token punctuation">(</span>update<span class="token punctuation">.</span>PodUID<span class="token punctuation">,</span> update<span class="token punctuation">.</span>ContainerID<span class="token punctuation">,</span> ready<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre>
<p><code>proberManager</code> 启动的时候，会运行一个 goroutine 定时读取 readinessManager 管道中的数据，并根据数据调用 <code>statusManager</code> 去更新 apiserver 中 pod 的状态信息。负责 Service 逻辑的组件获取到了这个状态，就能根据不同的值来决定是否需要更新 endpoints 的内容，也就是 service 的请求是否发送到这个 pod。</p>
<p>具体执行检测的代码在 <code>pkg/kubelet/prober/prober.go</code> 文件中，它会根据不同的 prober 方法（exec、HTTP、TCP）调用对应的处理逻辑，而这些具体的逻辑代码是在 <code>pkg/probe/</code> 文件夹中，三种方法的实现都不复杂，就不再详细解释了。</p>

                </div>
            </section>
        </article>
    </div>
    
<nav class="pagination">
    
    
    <a class="prev-post" title="kubernetes 权限管理" href="/2017/06/16/kubernetes-authentication-and-authorization/">
        ← kubernetes 权限管理
    </a>
    
    <span class="prev-next-post">•</span>
    
    <a class="next-post" title="kubelet 源码分析：Garbage Collect" href="/2017/06/09/kubelet-source-code-analysis-part-3/">
        kubelet 源码分析：Garbage Collect →
    </a>
    
    
</nav>

    <div class="inner">
    <!-- Begin Mailchimp Signup Form -->
    <link href="//cdn-images.mailchimp.com/embedcode/classic-10_7.css" rel="stylesheet" type="text/css">
    <style type="text/css">
    	#mc_embed_signup{background:#fff; clear:left; font:14px Helvetica,Arial,sans-serif; }
    	/* Add your own Mailchimp form style overrides in your site stylesheet or in this style block.
    	   We recommend moving this block and the preceding CSS link to the HEAD of your HTML file. */
    </style>
    <div id="mc_embed_signup">
    <form action="https://cizixs.us7.list-manage.com/subscribe/post?u=2d561b8dea52d73a2e05e6dcb&amp;id=5c710f135b" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
        <div id="mc_embed_signup_scroll">
    	<h2>订阅本博客，第一时间收到文章更新</h2>
    <div class="indicates-required"><span class="asterisk">*</span> indicates required</div>
    <div class="mc-field-group">
    	<label for="mce-EMAIL">邮件地址  <span class="asterisk">*</span>
    </label>
    	<input type="email" value="" name="EMAIL" class="required email" id="mce-EMAIL">
    </div>
    	<div id="mce-responses" class="clear">
    		<div class="response" id="mce-error-response" style="display:none"></div>
    		<div class="response" id="mce-success-response" style="display:none"></div>
    	</div>    <!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
        <div style="position: absolute; left: -5000px;" aria-hidden="true"><input type="text" name="b_2d561b8dea52d73a2e05e6dcb_5c710f135b" tabindex="-1" value=""></div>
        <div class="clear"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="button"></div>
        </div>
    </form>
    </div>
    <script type='text/javascript' src='//s3.amazonaws.com/downloads.mailchimp.com/js/mc-validate.js'></script><script type='text/javascript'>(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';}(jQuery));var $mcj = jQuery.noConflict(true);</script>
    <!--End mc_embed_signup-->
    </div>

    <div class="inner">
        <div id="disqus_thread"></div>
    </div>

    
</main>

<div class="t-g-control">
    <div class="gotop">
        <svg class="icon" width="32px" height="32px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M793.024 710.272a32 32 0 1 0 45.952-44.544l-310.304-320a32 32 0 0 0-46.4 0.48l-297.696 320a32 32 0 0 0 46.848 43.584l274.752-295.328 286.848 295.808z" fill="#8a8a8a" /></svg>
    </div>
    <div class="toc-control">
        <svg class="icon toc-icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M779.776 480h-387.2a32 32 0 0 0 0 64h387.2a32 32 0 0 0 0-64M779.776 672h-387.2a32 32 0 0 0 0 64h387.2a32 32 0 0 0 0-64M256 288a32 32 0 1 0 0 64 32 32 0 0 0 0-64M392.576 352h387.2a32 32 0 0 0 0-64h-387.2a32 32 0 0 0 0 64M256 480a32 32 0 1 0 0 64 32 32 0 0 0 0-64M256 672a32 32 0 1 0 0 64 32 32 0 0 0 0-64" fill="#8a8a8a" /></svg>
        <svg class="icon toc-close" style="display: none;" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 960c-247.039484 0-448-200.960516-448-448S264.960516 64 512 64 960 264.960516 960 512 759.039484 960 512 960zM512 128.287273c-211.584464 0-383.712727 172.128262-383.712727 383.712727 0 211.551781 172.128262 383.712727 383.712727 383.712727 211.551781 0 383.712727-172.159226 383.712727-383.712727C895.712727 300.415536 723.551781 128.287273 512 128.287273z" fill="#8a8a8a" /><path d="M557.05545 513.376159l138.367639-136.864185c12.576374-12.416396 12.672705-32.671738 0.25631-45.248112s-32.704421-12.672705-45.248112-0.25631l-138.560301 137.024163-136.447897-136.864185c-12.512727-12.512727-32.735385-12.576374-45.248112-0.063647-12.512727 12.480043-12.54369 32.735385-0.063647 45.248112l136.255235 136.671523-137.376804 135.904314c-12.576374 12.447359-12.672705 32.671738-0.25631 45.248112 6.271845 6.335493 14.496116 9.504099 22.751351 9.504099 8.12794 0 16.25588-3.103239 22.496761-9.247789l137.567746-136.064292 138.687596 139.136568c6.240882 6.271845 14.432469 9.407768 22.65674 9.407768 8.191587 0 16.352211-3.135923 22.591372-9.34412 12.512727-12.480043 12.54369-32.704421 0.063647-45.248112L557.05545 513.376159z" fill="#8a8a8a" /></svg>
    </div>
    <div class="gobottom">
        <svg class="icon" width="32px" height="32.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M231.424 346.208a32 32 0 0 0-46.848 43.584l297.696 320a32 32 0 0 0 46.4 0.48l310.304-320a32 32 0 1 0-45.952-44.544l-286.848 295.808-274.752-295.36z" fill="#8a8a8a" /></svg>
    </div>
</div>
<div class="toc-main" style="right: -100%">
    <div class="post-toc">
        <span>TOC</span>
        <ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#简介"><span class="toc-text">简介</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#StatusManager"><span class="toc-text">StatusManager</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#ProbeManager"><span class="toc-text">ProbeManager</span></a></li></ol>
    </div>
</div>



        

<aside class="read-next outer">
    <div class="inner">
        <div class="read-next-feed">
            
            

<article class="read-next-card"  style="background-image: url(https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxcn9ft3j318w0txdo6.jpg)"  >
  <header class="read-next-card-header">
    <small class="read-next-card-header-sitetitle">&mdash; Cizixs Write Here &mdash;</small>
    <h3 class="read-next-card-header-title">Recent Posts</h3>
  </header>
  <div class="read-next-divider">
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
      <path d="M13 14.5s2 3 5 3 5.5-2.463 5.5-5.5S21 6.5 18 6.5c-5 0-7 11-12 11C2.962 17.5.5 15.037.5 12S3 6.5 6 6.5s4.5 3.5 4.5 3.5"/>
    </svg>
  </div>
  <div class="read-next-card-content">
    <ul>
      
      
      
      <li>
        <a href="/2018/08/26/what-is-istio/">什么是 istio</a>
      </li>
      
      
      
      <li>
        <a href="/2018/08/25/knative-serverless-platform/">serverless 平台 knative 简介</a>
      </li>
      
      
      
      <li>
        <a href="/2018/06/25/kubernetes-resource-management/">kubernetes 资源管理概述</a>
      </li>
      
      
      
      <li>
        <a href="/2018/01/24/use-prometheus-and-grafana-to-monitor-linux-machine/">使用 promethues 和 grafana 监控自己的 linux 机器</a>
      </li>
      
      
      
      <li>
        <a href="/2018/01/13/linux-udp-packet-drop-debug/">linux 系统 UDP 丢包问题分析思路</a>
      </li>
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    </ul>
  </div>
  <footer class="read-next-card-footer">
    <a href="/archives">  MORE  → </a>
  </footer>
</article>


            
            
            
        </div>
    </div>
</aside>


<footer class="site-footer outer">

	<div class="site-footer-content inner">
		<section class="copyright">
			<a href="/" title="Cizixs Write Here">Cizixs Write Here</a>
			&copy; 2019
		</section>
		<nav class="site-footer-nav">
			
            <a href="https://hexo.io" title="Hexo" target="_blank" rel="noopener">Hexo</a>
            <a href="https://github.com/xzhih/hexo-theme-casper" title="Casper" target="_blank" rel="noopener">Casper</a>
        </nav>
    </div>
</footer>






<div class="floating-header" >
	<div class="floating-header-logo">
        <a href="/" title="Cizixs Write Here">
			
                <img src="https://cizixs-blog.oss-cn-beijing.aliyuncs.com/006tNc79ly1g1qxfovpzyj30740743yg.jpg" alt="Cizixs Write Here icon" />
			
            <span>Cizixs Write Here</span>
        </a>
    </div>
    <span class="floating-header-divider">&mdash;</span>
    <div class="floating-header-title">kubelet 源码分析：statusManager 和 probeManager</div>
    <progress class="progress" value="0">
        <div class="progress-container">
            <span class="progress-bar"></span>
        </div>
    </progress>
</div>
<script>
   $(document).ready(function () {
    var progressBar = document.querySelector('progress');
    var header = document.querySelector('.floating-header');
    var title = document.querySelector('.post-full-title');
    var lastScrollY = window.scrollY;
    var lastWindowHeight = window.innerHeight;
    var lastDocumentHeight = $(document).height();
    var ticking = false;

    function onScroll() {
        lastScrollY = window.scrollY;
        requestTick();
    }
    function requestTick() {
        if (!ticking) {
            requestAnimationFrame(update);
        }
        ticking = true;
    }
    function update() {
        var rect = title.getBoundingClientRect();
        var trigger = rect.top + window.scrollY;
        var triggerOffset = title.offsetHeight + 35;
        var progressMax = lastDocumentHeight - lastWindowHeight;
            // show/hide floating header
            if (lastScrollY >= trigger + triggerOffset) {
                header.classList.add('floating-active');
            } else {
                header.classList.remove('floating-active');
            }
            progressBar.setAttribute('max', progressMax);
            progressBar.setAttribute('value', lastScrollY);
            ticking = false;
        }

        window.addEventListener('scroll', onScroll, {passive: true});
        update();

        // TOC
        var width = $('.toc-main').width();
        $('.toc-control').click(function () {
            if ($('.t-g-control').css('width')=="50px") {
                if ($('.t-g-control').css('right')=="0px") {
                    $('.t-g-control').animate({right: width}, "slow");
                    $('.toc-main').animate({right: 0}, "slow");
                    toc_icon()
                } else {
                    $('.t-g-control').animate({right: 0}, "slow");
                    $('.toc-main').animate({right: -width}, "slow");
                    toc_icon()
                }
            } else {
                if ($('.toc-main').css('right')=="0px") {
                    $('.toc-main').slideToggle("fast", toc_icon());
                } else {
                    $('.toc-main').css('right', '0px');
                    toc_icon()
                }
            }
        })

        function toc_icon() {
            if ($('.toc-icon').css('display')=="none") {
                $('.toc-close').hide();
                $('.toc-icon').show();
            } else {
                $('.toc-icon').hide();
                $('.toc-close').show();
            }
        }

        $('.gotop').click(function(){
            $('html,body').animate({scrollTop:$('.post-full-header').offset().top}, 800);
        });
        $('.gobottom').click(function () {
            $('html,body').animate({scrollTop:$('.pagination').offset().top}, 800);
        });

        // highlight
        // https://highlightjs.org
        $('pre code').each(function(i, block) {
            hljs.highlightBlock(block);
        });
        $('td.code').each(function(i, block) {
            hljs.highlightBlock(block);
        });

        console.log("this theme is from https://github.com/xzhih/hexo-theme-casper")
    });
</script>



<link rel="stylesheet" href="https://cdn.staticfile.org/lightgallery/1.3.9/css/lightgallery.min.css">



<script src="https://cdn.staticfile.org/lightgallery/1.3.9/js/lightgallery.min.js"></script>


<script>
	$(function () {
		var postImg = $('#lightgallery').find('img');
		postImg.addClass('post-img');
		postImg.each(function () {
			var imgSrc = $(this).attr('src');
			$(this).attr('data-src', imgSrc);
		});
		$('#lightgallery').lightGallery({selector: '.post-img'});
	});
</script>



<script>

/**
*  RECOMMENDED CONFIGURATION VARIABLES: EDIT AND UNCOMMENT THE SECTION BELOW TO INSERT DYNAMIC VALUES FROM YOUR PLATFORM OR CMS.
*  LEARN WHY DEFINING THESE VARIABLES IS IMPORTANT: https://disqus.com/admin/universalcode/#configuration-variables*/

var disqus_config = function () {
this.page.url = 'http://cizixs.com/2017/06/12/kubelet-source-code-analysis-part4-status-manager/';  // Replace PAGE_URL with your page's canonical URL variable
this.page.identifier = 'http://cizixs.com/2017/06/12/kubelet-source-code-analysis-part4-status-manager/'; // Replace PAGE_IDENTIFIER with your page's unique identifier variable
};

(function() { // DON'T EDIT BELOW THIS LINE
var d = document, s = d.createElement('script');
s.src = 'https://cizixs.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
                            


    </div>
</body>
</html>
